package gui;

import gameManager.ExperimentsManager;
import gameManager.ExperimentsManagerGUI;
import gameManager.GameManager;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class MainFrame extends JFrame implements ExperimentsManagerGUI {

    private ExperimentsManager experimentsManager;
    private String[] algorithmNames = {"Random Algorithm", "Alpha-beta"};
    private JButton runButton = new JButton("Run");
    private JTextField dealerSeed = new JTextField("1");
    private JTextField upperPlayerDepth = new JTextField("1000");
    private JTextField upperPlayerHands = new JTextField("1000");
    private JTextField upperPlayerSeed = new JTextField("1");
    private JComboBox upperPlayerAlgorithms = new JComboBox(algorithmNames);
    private JTextField downPlayerDepth = new JTextField("1000");
    private JTextField downPlayerHands = new JTextField("1000");
    private JTextField downPlayerSeed = new JTextField("1");
    private JComboBox downPlayerAlgorithms = new JComboBox(algorithmNames);
    
    private JTextField numGames = new JTextField("100");
    
    private JTextArea resultsArea = new JTextArea(15, 50);

    public MainFrame() {
        try {
            jbInit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void jbInit() throws Exception {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setTitle("Domino");

        //UPPER PLAYER
        JPanel upperPlayerPanel = new JPanel();
        upperPlayerPanel.setLayout(new BoxLayout(upperPlayerPanel, BoxLayout.Y_AXIS));
        upperPlayerPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Upper player"),
                BorderFactory.createEmptyBorder(1, 1, 1, 1)));        

        JPanel upperPlayerAlgorithmPanel = new JPanel(new FlowLayout());
        upperPlayerAlgorithmPanel.add(new JLabel("Algorithm: "));
        upperPlayerAlgorithmPanel.add(upperPlayerAlgorithms);
        upperPlayerAlgorithms.setSelectedIndex(0);
        upperPlayerPanel.add(upperPlayerAlgorithmPanel);

        JPanel upperPlayerDepthPanel = new JPanel(new FlowLayout());
        upperPlayerDepthPanel.add(new JLabel("Max. search depth: "));
        upperPlayerDepth.setColumns(4);
        upperPlayerDepthPanel.add(upperPlayerDepth);
        upperPlayerPanel.add(upperPlayerDepthPanel);

        JPanel upperPlayerHandsPanel = new JPanel(new FlowLayout());
        upperPlayerHandsPanel.add(new JLabel("Max. hands: "));
        upperPlayerHands.setColumns(4);
        upperPlayerHandsPanel.add(upperPlayerHands);
        upperPlayerHandsPanel.add(new JLabel("First seed: "));
        upperPlayerSeed.setColumns(2);
        upperPlayerHandsPanel.add(upperPlayerSeed);
        upperPlayerPanel.add(upperPlayerHandsPanel);


        //DOWN PLAYER
        JPanel downPlayerPanel = new JPanel();
        downPlayerPanel.setLayout(new BoxLayout(downPlayerPanel, BoxLayout.Y_AXIS));
        downPlayerPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Down player"),
                BorderFactory.createEmptyBorder(1, 1, 1, 1)));

        JPanel downPlayerAlgorithmPanel = new JPanel(new FlowLayout());
        downPlayerAlgorithmPanel.add(new JLabel("Algorithm: "));
        downPlayerAlgorithmPanel.add(downPlayerAlgorithms);
        downPlayerAlgorithms.setSelectedIndex(0);
        downPlayerPanel.add(downPlayerAlgorithmPanel);

        JPanel downPlayerDepthPanel = new JPanel(new FlowLayout());
        downPlayerDepthPanel.add(new JLabel("Max. search depth: "));
        downPlayerDepth.setColumns(4);
        downPlayerDepthPanel.add(downPlayerDepth);
        downPlayerPanel.add(downPlayerDepthPanel);

        JPanel downPlayerHandsPanel = new JPanel(new FlowLayout());
        downPlayerHandsPanel.add(new JLabel("Max. hands: "));
        downPlayerHands.setColumns(4);
        downPlayerHandsPanel.add(downPlayerHands);
        downPlayerHandsPanel.add(new JLabel("First seed: "));
        downPlayerSeed.setColumns(2);
        downPlayerHandsPanel.add(downPlayerSeed);
        downPlayerPanel.add(downPlayerHandsPanel);

        //GAMES
        JPanel dealerPanel = new JPanel();
        dealerPanel.setLayout(new BoxLayout(dealerPanel, BoxLayout.Y_AXIS));
        dealerPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Experiments: "),
                BorderFactory.createEmptyBorder(1, 1, 1, 1)));        
        
        JPanel numExperimentsPanel = new JPanel(new FlowLayout());
        numExperimentsPanel.add(new JLabel("Number of games: "));
        numGames.setColumns(4);
        numExperimentsPanel.add(numGames);
        dealerPanel.add(numExperimentsPanel);
        
        JPanel dealerFirstSeedPanel = new JPanel(new FlowLayout());
        dealerFirstSeedPanel.add(new JLabel("Dealer first seed:"));
        dealerSeed.setColumns(2);
        dealerFirstSeedPanel.add(dealerSeed);
        dealerPanel.add(dealerFirstSeedPanel);
      
        runButton.addActionListener(new RunButton_actionAdapter(this));
        dealerPanel.add(runButton);

        //CONFIGURATION PANEL
        JPanel configurationPanel = new JPanel();
        configurationPanel.setLayout(new BoxLayout(configurationPanel, BoxLayout.Y_AXIS));

        configurationPanel.add(upperPlayerPanel);
        configurationPanel.add(downPlayerPanel);
        configurationPanel.add(dealerPanel);

        //RESULTS PANEL
        JPanel resultsPanel = new JPanel();
        resultsPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Results: "),
                BorderFactory.createEmptyBorder(1, 1, 1, 1)));        
        resultsPanel.add(resultsArea);

        //GLOBAL STRUTCURE
        JPanel contentPane = (JPanel) this.getContentPane();
        contentPane.setLayout(new BorderLayout());

        JPanel globalPanel = new JPanel(new FlowLayout());
        globalPanel.add(configurationPanel);
        globalPanel.add(resultsPanel);
        contentPane.add(globalPanel);

        experimentsManager = new ExperimentsManager(this);

        pack();
    }

    public void jRunButton_actionPerformed(ActionEvent e) {
        runButton.setEnabled(false);

        experimentsManager.setUpperPlayerConfiguration(
                Integer.parseInt(upperPlayerDepth.getText()), Integer.parseInt(upperPlayerHands.getText()), Integer.parseInt(upperPlayerSeed.getText()),
                (upperPlayerAlgorithms.getSelectedIndex() == 0) ? GameManager.RANDOM_ALGORITHM : GameManager.ALPHA_BETA);

        experimentsManager.setDownPlayerConfiguration(
                Integer.parseInt(downPlayerDepth.getText()), Integer.parseInt(downPlayerHands.getText()), Integer.parseInt(downPlayerSeed.getText()),
                (downPlayerAlgorithms.getSelectedIndex() == 0) ? GameManager.RANDOM_ALGORITHM : GameManager.ALPHA_BETA);

        experimentsManager.run(Integer.parseInt(numGames.getText()), Integer.parseInt(dealerSeed.getText()));
    }

    @Override
    public void showResults(String winner) {
        resultsArea.setText(winner);
        runButton.setEnabled(true);
    }
}

class RunButton_actionAdapter implements ActionListener {

    private MainFrame adaptee;

    RunButton_actionAdapter(MainFrame adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        adaptee.jRunButton_actionPerformed(e);
    }
}
